package cn.qn.service.impl.image;

import cn.qn.moudle.image.Image;
import cn.qn.properties.OSSPolicy;
import cn.qn.properties.OSSProperties;
import cn.qn.repository.image.ImageRepository;
import cn.qn.service.image.ImageService;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.Date;

/**
 * @Auther: Bryant
 * @Date: 2018/6/11
 * @Description:
 */
@com.alibaba.dubbo.config.annotation.Service(interfaceClass = ImageService.class)
@Service
public class ImageServiceImpl implements ImageService {
    
    private Logger LOGGER = LoggerFactory.getLogger(ImageService.class);

    @Autowired
    private ImageRepository imageRepository;


    @Value("${aliyun.oss.endpoint}")
    private String endpoint;
    @Value("${aliyun.oss.accessId}")
    private String accessId;
    @Value("${aliyun.oss.accessKey}")
    private String accessKey;
    @Value("${aliyun.oss.bucket}")
    private String bucket;
    @Value("${aliyun.oss.privateBucket}")
    private String privateBucket;
    @Value("${aliyun.oss.baseDir}")
    private String baseDir;
    @Value("${aliyun.oss.region}")
    private String region;
    @Value("${aliyun.oss.showUrl}")
    private String showUrl;

    @Override
    public Image insert(Image image) {
        return imageRepository.save(image);
    }

    @Override
    public Image findById(Integer id) {
        if(null == id){
            return null;
        }
        return imageRepository.findImageById(id);
    }

    @Override
    public void delete(Integer id) {
        imageRepository.deleteById(id);
    }

    /**
     * 生成oss policy 信息,用于前端上传
     * @return
     * @see
     * @throws
     */
    @Override
    public OSSPolicy generatePolicy(String type, String filePath){
        OSSProperties ossProperties = getOSSProperties(filePath);
        String endpoint = ossProperties.getEndpoint();
        String accessId = ossProperties.getAccessId();
        String accessKey = ossProperties.getAccessKey();
        String bucket =ossProperties.getBucket();
        String baseDir = ossProperties.getBaseDir();

        String dir = "";
        if(StringUtils.isNotBlank(type) && "app".equals(type)){
            dir = filePath;
        }else{
            dir = baseDir+"/"+filePath;
        }

        String host = "https://" + bucket + "." + endpoint;
        OSSClient client = new OSSClient(endpoint, accessId, accessKey);
        OSSPolicy ossPolicy=new OSSPolicy();
        try{
            long expireTime = 120;
            long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
            Date expiration = new Date(expireEndTime);
            PolicyConditions policyConds = new PolicyConditions();
            policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
            policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);

            String postPolicy = client.generatePostPolicy(expiration, policyConds);
            byte[] binaryData = postPolicy.getBytes("utf-8");
            String encodedPolicy = BinaryUtil.toBase64String(binaryData);
            String postSignature = client.calculatePostSignature(postPolicy);
            ossPolicy.setAccessId(accessId);
            ossPolicy.setDir(dir);
            ossPolicy.setExpire(String.valueOf(expireEndTime/1000));
            ossPolicy.setSignature(postSignature);
            ossPolicy.setHost(host);
            ossPolicy.setPolicy(encodedPolicy);
        }catch(Exception e){
            LOGGER.error("生成上传policy错误",e);
        }
        return ossPolicy;
    }

    /**
     * 生成oss private policy 信息,用于前端上传
     * @return
     * @see
     * @throws
     */
    @Override
    public  OSSPolicy generatePrivatePolicy(String filePath){
        OSSProperties ossProperties = getOSSProperties(filePath);
        String endpoint = ossProperties.getEndpoint();
        String accessId = ossProperties.getAccessId();
        String accessKey = ossProperties.getAccessKey();
        String private_bucket =ossProperties.getPrivateBucket();
        String baseDir = ossProperties.getBaseDir();

        String host = "https://" + private_bucket + "." + endpoint;
        OSSClient client = new OSSClient(endpoint, accessId, accessKey);
        OSSPolicy ossPolicy=new OSSPolicy();
        String dir=baseDir+"/"+filePath;
        try{
            long expireTime = 120;
            long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
            Date expiration = new Date(expireEndTime);
            PolicyConditions policyConds = new PolicyConditions();
            policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
            policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);

            String postPolicy = client.generatePostPolicy(expiration, policyConds);
            byte[] binaryData = postPolicy.getBytes("utf-8");
            String encodedPolicy = BinaryUtil.toBase64String(binaryData);
            String postSignature = client.calculatePostSignature(postPolicy);
            ossPolicy.setAccessId(accessId);
            ossPolicy.setDir(dir);
            ossPolicy.setExpire(String.valueOf(expireEndTime/1000));
            ossPolicy.setSignature(postSignature);
            ossPolicy.setHost(host);
            ossPolicy.setPolicy(encodedPolicy);
        }catch(Exception e){
            LOGGER.error("生成上传policy错误",e);
        }
        return ossPolicy;
    }

    /**
     * 生成临时访问的URL
     * @return
     * @see
     * @throws
     */
    @Override
    public  String generatePresignedUrl(String objectKey){
        OSSProperties ossProperties = getOSSProperties("");
        String endpoint = ossProperties.getEndpoint();
        String accessId = ossProperties.getAccessId();
        String accessKey = ossProperties.getAccessKey();
        String private_bucket =ossProperties.getPrivateBucket();
        String baseDir = ossProperties.getBaseDir();
        OSSClient client = new OSSClient(endpoint, accessId, accessKey);
        long expireTime = 120;
        long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
        Date expiration = new Date(expireEndTime);
        return client.generatePresignedUrl(private_bucket, baseDir+"/"+objectKey, expiration).toString();

    }

    /**
     * 删除对象
     * @param objectKey
     * @see
     * @throws
     */
    @Override
    public  void deleteObject(String objectKey){
        OSSProperties ossProperties = getOSSProperties("");
        String endpoint = ossProperties.getEndpoint();
        String accessId = ossProperties.getAccessId();
        String accessKey = ossProperties.getAccessKey();
        String bucket =ossProperties.getBucket();
        String baseDir = ossProperties.getBaseDir();
        OSSClient ossClient = new OSSClient(endpoint, accessId, accessKey);
        LOGGER.info("删除对象:" + objectKey);
        ossClient.deleteObject(bucket, baseDir + "/" + objectKey);
    }

    /**
     * 上传对象
     * @param objectKey
     * @see
     * @throws
     */
    @Override
    public  void uploadObject(String objectKey, byte[] byteArray){
        OSSProperties ossProperties = getOSSProperties("");
        String endpoint = ossProperties.getEndpoint();
        String accessId = ossProperties.getAccessId();
        String accessKey = ossProperties.getAccessKey();
        String bucket =ossProperties.getBucket();
        String baseDir = ossProperties.getBaseDir();
        OSSClient ossClient = new OSSClient(endpoint, accessId, accessKey);
        LOGGER.info("上传对象:" + objectKey);
        ossClient.putObject(bucket, baseDir + "/" + objectKey, new ByteArrayInputStream(byteArray));
    }

    /**
     * 上传对象
     * @param objectKey
     * @see
     * @throws
     */
    @Override
    public  void uploadPrivateObject(String objectKey, InputStream input){
        OSSProperties ossProperties = getOSSProperties("");
        String endpoint = ossProperties.getEndpoint();
        String accessId = ossProperties.getAccessId();
        String accessKey = ossProperties.getAccessKey();
        String private_bucket =ossProperties.getPrivateBucket();
        String baseDir = ossProperties.getBaseDir();
        OSSClient ossClient = new OSSClient(endpoint, accessId, accessKey);
        LOGGER.info("上传对象:" + objectKey);
        ossClient.putObject(private_bucket, baseDir + "/" + objectKey, input);
    }

    /**
     * 上传对象
     * @param objectKey
     * @see
     * @throws
     */
    @Override
    public  void uploadPrivateObject(String objectKey, byte[] byteArray){
        OSSProperties ossProperties = getOSSProperties("");
        String endpoint = ossProperties.getEndpoint();
        String accessId = ossProperties.getAccessId();
        String accessKey = ossProperties.getAccessKey();
        String private_bucket =ossProperties.getPrivateBucket();
        String baseDir = ossProperties.getBaseDir();
        OSSClient ossClient = new OSSClient(endpoint, accessId, accessKey);
        LOGGER.info("上传对象:" + objectKey);
        ossClient.putObject(private_bucket, baseDir + "/" + objectKey, new ByteArrayInputStream(byteArray));
    }

    /**
     * 上传对象
     * @param objectKey
     * @see
     * @throws
     */
    @Override
    public  void uploadObject(String objectKey, InputStream input){
        OSSProperties ossProperties = getOSSProperties("");
        String endpoint = ossProperties.getEndpoint();
        String accessId = ossProperties.getAccessId();
        String accessKey = ossProperties.getAccessKey();
        String bucket =ossProperties.getBucket();
        String baseDir = ossProperties.getBaseDir();
        OSSClient ossClient = new OSSClient(endpoint, accessId, accessKey);
        LOGGER.info("上传对象:" + objectKey);
        ossClient.putObject(bucket, baseDir + "/" + objectKey, input);
    }
    @Override
    public  InputStream downloadPrivateObject(String objectKey){
        OSSProperties ossProperties = getOSSProperties("");
        String endpoint = ossProperties.getEndpoint();
        String accessId = ossProperties.getAccessId();
        String accessKey = ossProperties.getAccessKey();
        String private_bucket =ossProperties.getPrivateBucket();
        String baseDir = ossProperties.getBaseDir();
        OSSClient ossClient = new OSSClient(endpoint, accessId, accessKey);
        LOGGER.info("下载对象:" + objectKey);
        return ossClient.getObject(private_bucket,  baseDir + objectKey).getObjectContent();
    }
    @Override
    public  String getObjectPrefix(){
        OSSProperties ossProperties = getOSSProperties("");
        String endpoint = ossProperties.getEndpoint();
        String bucket =ossProperties.getBucket();
        String baseDir = ossProperties.getBaseDir();
        return new StringBuilder().append("https://").append(bucket).append(".").append(endpoint).append("/").append(baseDir).toString();
    }
    @Override
    public  String getHost(){
        OSSProperties ossProperties = getOSSProperties("");
        String endpoint = ossProperties.getEndpoint();
        String bucket =ossProperties.getBucket();
        return new StringBuilder().append("https://").append(bucket).append(".").append(endpoint).append("/").toString();
    }
    @Override
    public  String generateFileName(){
        return new StringBuilder().append(RandomStringUtils.randomAlphanumeric(10)).append(System.currentTimeMillis()).toString();
    }

    @Override
    public OSSProperties getOSSProperties(String filePath) {
        OSSProperties properties = new OSSProperties();
        properties.setBaseDir(baseDir+filePath);
        properties.setAccessId(accessId);
        properties.setAccessKey(accessKey);
        properties.setBucket(bucket);
        properties.setEndpoint(endpoint);
        properties.setPrivateBucket(privateBucket);
        properties.setRegion(region);
        properties.setShowUrl(showUrl);
        return properties;
    }

    /**
     * 通过图片ID查询图片完整路径
     * @param imageId
     * @return
     */
    @Override
    @Cacheable(value = "imageDetail",key = "T(String).valueOf('imageDetail').concat(#imageId)")
    public String getFullPathByImageId(Integer imageId) {
        Image image=findById(imageId);
        if(null!=image){
            return showUrl+image.getPath();
        }
        return null;
    }


    @Override
    public Boolean deleteAppObject(String objectKey) {
        OSSProperties ossProperties = getOSSProperties("");
        String endpoint = ossProperties.getEndpoint();
        String accessId = ossProperties.getAccessId();
        String accessKey = ossProperties.getAccessKey();
        String bucket =ossProperties.getBucket();
        OSSClient ossClient = new OSSClient(endpoint, accessId, accessKey);
        LOGGER.info("删除对象:" + objectKey);
        ossClient.deleteObject(bucket, objectKey);
        return true;
    }
}
